#ifndef     __RESP_FUTURE_H
#define     __RESP_FUTURE_H

#include "./message.h"
#include "../rtos/cond_var.h"

namespace conn {

class RespFuture {

public:
    static constexpr uint16_t REQ_FREE = 0xFFFF;

    void free() {
        m_req_id = REQ_FREE;
        m_flag = false;
        m_cond.reset();
    }

    inline uint16_t request_id() const {
        return m_req_id;
    }

    bool acquire(uint16_t id) {
        if (m_req_id == REQ_FREE) {
            m_req_id = id;
            return true;
        }
        return false;
    }

    void set(const Message &msg) {
        m_cond.lock();
        m_msg = msg;
        m_flag = true;
        m_cond.notify();
        m_cond.unlock();
    }

    bool wait(Message &msg, uint32_t timeout = osWaitForever) {
        do {
            m_cond.lock();
            if (!m_flag) {
                m_cond.unlock();
                if (!m_cond.wait(timeout)) {
                    return false;
                }
                continue;
            }
        } while (false);
        msg = m_msg;
        m_cond.unlock();
        return true;
    }

private:
    rtos::CondVar m_cond;
    bool m_flag = false;

    Message m_msg;
    uint16_t m_req_id = REQ_FREE;
};

struct RespInfo {
    RespFuture *ptr;
    uint8_t dest;
    uint8_t req;
};

}

#endif
